<!DOCTYPE html>
<html lang="en" class="dark">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AuthTuna 🐟 - Asynchronous Security Framework</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&display=swap" rel="stylesheet">

    <!-- Highlight.js for Syntax Highlighting -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
    <!-- Load required language definitions -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/python.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/bash.min.js"></script>

    <style>
        :root {
            --primary: #8b5cf6; /* Indigo-500 */
        }
        body {
            font-family: 'Inter', sans-serif;
            background-color: #030712; /* Gray-950 */
        }
        /* Custom scrolling for content area */
        .doc-content-area::-webkit-scrollbar { width: 8px; }
        .doc-content-area::-webkit-scrollbar-thumb { background-color: #374151; border-radius: 4px; }
        .doc-content-area::-webkit-scrollbar-track { background: #1f2937; }

        /* Prose styling equivalent for generated content */
        .prose h1, .prose h2, .prose h3 {
            color: #f3f4f6; /* White */
            margin-top: 2rem;
            margin-bottom: 1rem;
        }
        .prose h1 { font-size: 2.5rem; font-weight: 800; }
        .prose h2 { font-size: 1.75rem; font-weight: 700; border-bottom: 1px solid #374151; padding-bottom: 0.5rem; }
        .prose h3 { font-size: 1.25rem; font-weight: 600; }
        .prose p, .prose li { color: #d1d5db; line-height: 1.7; }
        .prose ul { list-style-type: disc; margin-left: 1.5rem; margin-bottom: 1rem; }
        .prose code {
            background-color: #1f2937; /* Gray-800 */
            padding: 0.2rem 0.4rem;
            border-radius: 0.375rem;
            color: #facc15; /* Amber-400 */
            font-size: 0.875rem;
        }
        .prose pre {
            background-color: #111827; /* Gray-900 */
            border: 1px solid #374151;
            padding: 1rem;
            border-radius: 0.5rem;
            overflow-x: auto;
            margin-top: 1rem;
            margin-bottom: 1rem;
        }
        .prose pre code {
            background: none;
            color: #e5e7eb; /* Gray-200 */
            padding: 0;
            font-size: 1rem;
        }
    </style>
</head>
<body class="text-gray-200">

    <div class="flex h-screen overflow-hidden">

        <!-- Sidebar Navigation -->
        <nav id="sidebar" class="w-64 bg-gray-900 p-6 border-r border-gray-800 flex-shrink-0 overflow-y-auto">
            <div class="sticky top-0 pb-6 bg-gray-900 z-10">
                <h1 class="text-3xl font-extrabold text-indigo-400">AuthTuna 🐟</h1>
                <p class="text-sm text-gray-500 mt-1">v0.1.x Docs</p>
            </div>

            <div class="space-y-2">
                <h2 class="text-lg font-semibold text-gray-400 mt-4 mb-2 uppercase tracking-wider">Fundamentals</h2>
                <a href="#introduction" onclick="navigate('introduction')" class="nav-link block p-2 rounded-lg transition-colors hover:bg-gray-800" data-page="introduction">
                    Introduction & Setup
                </a>
                <a href="#configuration" onclick="navigate('configuration')" class="nav-link block p-2 rounded-lg transition-colors hover:bg-gray-800" data-page="configuration">
                    Configuration (`Settings`)
                </a>
                <a href="#core-managers" onclick="navigate('core-managers')" class="nav-link block p-2 rounded-lg transition-colors hover:bg-gray-800" data-page="core-managers">
                    Core Service Layer
                </a>

                <h2 class="text-lg font-semibold text-gray-400 mt-6 mb-2 uppercase tracking-wider">FastAPI Integration</h2>
                <a href="#dependencies" onclick="navigate('dependencies')" class="nav-link block p-2 rounded-lg transition-colors hover:bg-gray-800" data-page="dependencies">
                    Dependencies
                </a>
                <a href="#permission-dependencies" onclick="navigate('permission-dependencies')" class="nav-link block p-2 rounded-lg transition-colors hover:bg-gray-800" data-page="permission-dependencies">
                    Role & Permission Checks
                </a>
                <a href="#rbac-management" onclick="navigate('rbac-management')" class="nav-link block p-2 rounded-lg transition-colors hover:bg-gray-800" data-page="rbac-management">
                    RBAC Management (Admin API)
                </a>

                <h2 class="text-lg font-semibold text-gray-400 mt-6 mb-2 uppercase tracking-wider">Built-in Features</h2>
                <a href="#auth-flows" onclick="navigate('auth-flows')" class="nav-link block p-2 rounded-lg transition-colors hover:bg-gray-800" data-page="auth-flows">
                    Authentication Flows
                </a>
                <a href="#mfa" onclick="navigate('mfa')" class="nav-link block p-2 rounded-lg transition-colors hover:bg-gray-800" data-page="mfa">
                    MFA & Social Login (SSO)
                </a>
                <a href="#middleware-session" onclick="navigate('middleware-session')" class="nav-link block p-2 rounded-lg transition-colors hover:bg-gray-800" data-page="middleware-session">
                    Middleware & Session Mgmt
                </a>

            </div>
        </nav>

        <!-- Main Content Area -->
        <main class="flex-1 overflow-y-auto p-8 lg:p-12 doc-content-area">
            <div id="content" class="prose max-w-4xl mx-auto">
                <!-- Content will be injected here -->
            </div>
        </main>
    </div>

    <script>
        const contentDiv = document.getElementById('content');
        const navLinks = document.querySelectorAll('.nav-link');
        const pages = {};

        // --- Documentation Content (Simulated Pages) ---
        pages['introduction'] = `
            <h1>AuthTuna 🐟 - High-Performance Async Security</h1>
            <p class="lead">AuthTuna is a modern, batteries-included authentication and authorization framework for Python, designed specifically for **FastAPI** applications, but with a framework-agnostic core.</p>

            <h2>Key Features</h2>
            <ul>
                <li><strong>Async-First:</strong> Built entirely with asynchronous managers and SQLAlchemy 2.0.</li>
                <li><strong>Robust Sessions:</strong> DB-backed sessions with anti-hijack checks (device/region/IP mismatch).</li>
                <li><strong>Comprehensive RBAC:</strong> Hierarchical roles, fine-grained **Scoped Permissions**.</li>
                <li><strong>Built-in Flows:</strong> Ready-to-use routers for Login, Signup, MFA, Password Reset, and Social SSO.</li>
                <li><strong>Auditing:</strong> Logs all critical security events (login, password change, suspension).</li>
            </ul>

            <h2>Getting Started (Minimal Setup)</h2>
            <p>Install dependencies and initialize your FastAPI application:</p>
            <pre><code class="language-bash">pip install authtuna fastapi uvicorn aiosqlite python-dotenv</code></pre>

            <h3>1. Create a minimal .env file</h3>
            <pre><code class="language-bash"># .env
API_BASE_URL=http://localhost:8000
# Mandatory encryption keys (rotate periodically!)
FERNET_KEYS='["YOUR_PRIMARY_KEY", "YOUR_SECONDARY_KEY"]'
JWT_SECRET_KEY="a-strong-jwt-secret"
DEFAULT_DATABASE_URI=sqlite+aiosqlite:///./authtuna.db
</code></pre>

            <h3>2. Initialize the App</h3>
            <pre><code class="language-python">from fastapi import FastAPI, Depends
from authtuna import init_app
from authtuna.integrations import get_current_user
from authtuna.core.database import User

app = FastAPI(title="AuthTuna Demo API")
init_app(app) # Adds middleware and all routers

@app.get("/me")
async def read_user_self(user: User = Depends(get_current_user)):
    return {"username": user.username, "mfa_enabled": user.mfa_enabled}
</code></pre>
        `;

        pages['configuration'] = `
            <h1>Configuration (\`Settings\` Reference)</h1>
            <p>AuthTuna uses Pydantic settings, loading configuration from environment variables or a <code>.env</code> file. Secrets use <code>SecretStr</code> to prevent accidental logging.</p>

            <h2>Critical & Database Settings</h2>
            <div class="overflow-x-auto">
                <table class="w-full text-sm text-left text-gray-400 rounded-lg">
                    <thead class="text-xs uppercase bg-gray-800 text-gray-300">
                        <tr>
                            <th scope="col" class="py-3 px-6">Variable</th>
                            <th scope="col" class="py-3 px-6">Default</th>
                            <th scope="col" class="py-3 px-6">Description</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr class="bg-gray-900 border-b border-gray-800">
                            <th scope="row" class="py-4 px-6 font-medium whitespace-nowrap text-white">API_BASE_URL</th>
                            <td class="py-4 px-6">Required</td>
                            <td class="py-4 px-6">Base URL for generating email links and OAuth redirects.</td>
                        </tr>
                        <tr class="bg-gray-900 border-b border-gray-800">
                            <th scope="row" class="py-4 px-6 font-medium whitespace-nowrap text-white">FERNET_KEYS</th>
                            <td class="py-4 px-6">Required</td>
                            <td class="py-4 px-6">Comma-separated list of base64 keys for session/sensitive data encryption (supports rotation).</td>
                        </tr>
                        <tr class="bg-gray-900 border-b border-gray-800">
                            <th scope="row" class="py-4 px-6 font-medium whitespace-nowrap text-white">DEFAULT_DATABASE_URI</th>
                            <td class="py-4 px-6">sqlite+aiosqlite:///./authtuna_dev.db</td>
                            <td class="py-4 px-6">Async SQLAlchemy connection string.</td>
                        </tr>
                        <tr class="bg-gray-900 border-b border-gray-800">
                            <th scope="row" class="py-4 px-6 font-medium whitespace-nowrap text-white">AUTO_CREATE_DATABASE</th>
                            <td class="py-4 px-6">True</td>
                            <td class="py-4 px-6">Creates tables and provisions default roles/users on startup.</td>
                        </tr>
                    </tbody>
                </table>
            </div>

            <h2>Session & Security Settings</h2>
            <div class="overflow-x-auto">
                <table class="w-full text-sm text-left text-gray-400 rounded-lg">
                    <thead class="text-xs uppercase bg-gray-800 text-gray-300">
                        <tr>
                            <th scope="col" class="py-3 px-6">Variable</th>
                            <th scope="col" class="py-3 px-6">Default</th>
                            <th scope="col" class="py-3 px-6">Description</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr class="bg-gray-900 border-b border-gray-800">
                            <th scope="row" class="py-4 px-6 font-medium whitespace-nowrap text-white">SESSION_LIFETIME_SECONDS</th>
                            <td class="py-4 px-6">604800 (7 days)</td>
                            <td class="py-4 px-6">Time until session times out from inactivity.</td>
                        </tr>
                        <tr class="bg-gray-900 border-b border-gray-800">
                            <th scope="row" class="py-4 px-6 font-medium whitespace-nowrap text-white">SESSION_ABSOLUTE_LIFETIME_SECONDS</th>
                            <td class="py-4 px-6">31536000 (1 year)</td>
                            <td class="py-4 px-6">Absolute maximum session duration.</td>
                        </tr>
                        <tr class="bg-gray-900 border-b border-gray-800">
                            <th scope="row" class="py-4 px-6 font-medium whitespace-nowrap text-white">STRATEGY</th>
                            <td class="py-4 px-6">COOKIE</td>
                            <td class="py-4 px-6">Authentication mechanism: <code>COOKIE</code> or <code>BEARER</code>.</td>
                        </tr>
                         <tr class="bg-gray-900 border-b border-gray-800">
                            <th scope="row" class="py-4 px-6 font-medium whitespace-nowrap text-white">FINGERPRINT_HEADERS</th>
                            <td class="py-4 px-6">["User-Agent", "Accept-Language"]</td>
                            <td class="py-4 px-6">Headers used by the middleware to detect session hijacking.</td>
                        </tr>
                    </tbody>
                </table>
            </div>
        `;

        pages['core-managers'] = `
            <h1>Core Service Layer (\`AuthTunaAsync\`)</h1>
            <p>The entire library core is exposed through asynchronous manager classes found in <code>authtuna.manager.asynchronous.py</code>. The main entry point is the <code>auth_service</code> instance from the FastAPI integration.</p>

            <h2>UserManager</h2>
            <p>Handles user lifecycle and data management.</p>
            <pre><code class="language-python"># Example: Suspending a user
from authtuna.integrations import auth_service

async def suspend(user_id, admin_id):
    suspended_user = await auth_service.users.suspend_user(
        user_id=user_id,
        admin_id=admin_id,
        reason="Violated ToS"
    )
    return suspended_user.is_active # Should be False
</code></pre>

            <h2>SessionManager</h2>
            <p>Directly manages database sessions, terminations, and retrieval.</p>
            <pre><code class="language-python"># Example: Terminate all other sessions for a user
async def cleanup_sessions(user_id, current_session_id, ip_address):
    await auth_service.sessions.terminate_all_for_user(
        user_id=user_id,
        ip_address=ip_address,
        except_session_id=current_session_id
    )
</code></pre>

            <h2>MFAManager & TokenManager</h2>
            <p>Handle Multi-Factor Authentication setups (TOTP) and time-limited security tokens (email verification, password reset, MFA validation).</p>
            <pre><code class="language-python"># Example: Creating a password reset token
token = await auth_service.tokens.create(
    user_id="user_id_abc",
    purpose="password_reset",
    expiry_seconds=3600
)
</code></pre>
        `;

        pages['dependencies'] = `
            <h1>FastAPI Integration: Dependencies</h1>
            <p>AuthTuna provides powerful FastAPI dependencies to handle authentication and authorization efficiently, relying on the middleware to inject session details into <code>request.state</code>.</p>

            <h2>\`get_current_user\`</h2>
            <p>The standard authentication dependency. Retrieves the complete <code>User</code> object from the database (with roles/permissions pre-loaded once per request) or raises <code>401 Unauthorized</code>.</p>
            <pre><code class="language-python">from fastapi import Depends
from authtuna.integrations import get_current_user
from authtuna.core.database import User

@router.get("/profile/full")
async def get_full_user(user: User = Depends(get_current_user)):
    return {"username": user.username, "roles": user.roles}
</code></pre>

            <h2>\`get_current_user_optional\`</h2>
            <p>Used for routes accessible to both authenticated and unauthenticated users (e.g., a public homepage).</p>
            <pre><code class="language-python">from typing import Optional
from authtuna.integrations import get_current_user_optional

@router.get("/")
async def homepage(user: Optional[User] = Depends(get_current_user_optional)):
    if user:
        return f"Hello, {user.username}"
    return "Hello, Guest"
</code></pre>

            <h2>\`get_user_ip\`</h2>
            <p>A simple dependency to retrieve the client's determined IP address from the request state.</p>
            <pre><code class="language-python">from authtuna.integrations import get_user_ip

@router.get("/ip")
async def show_ip(ip: str = Depends(get_user_ip)):
    return {"ip_address": ip}
</code></pre>
        `;

        pages['permission-dependencies'] = `
            <h1>Role & Permission Checks</h1>
            <p>The AuthTuna RBAC system supports role hierarchy, explicit role-to-role assignment permissions, and fine-grained permissions attached to roles.</p>

            <h2>\`RoleChecker\` (Simple Role Enforcement)</h2>
            <p>Enforces that the user has all specified roles. Raises <code>403 Forbidden</code> if roles are missing.</p>
            <pre><code class="language-python">from authtuna.integrations import RoleChecker

# Requires BOTH 'Admin' AND 'Moderator' roles
@router.delete("/content/{id}", dependencies=[Depends(RoleChecker("Admin", "Moderator"))])
async def delete_content():
    return {"status": "Deletion authorized"}
</code></pre>

            <h2>\`PermissionChecker\` (Scoped Authorization)</h2>
            <p>The most flexible authorization dependency. Checks for a named permission and supports scoping based on URL parameters.</p>

            <h3>1. Basic Permission Check (Global)</h3>
            <pre><code class="language-python">@router.get("/analytics", dependencies=[Depends(PermissionChecker("data:view:analytics"))])
async def get_analytics():
    return {"data": "viewing allowed"}
</code></pre>

            <h3>2. Scoped Permission Check (Context-Aware)</h3>
            <p>The <code>scope_from_path</code> parameter automatically constructs the scope string (e.g., <code>project:456</code>) and checks only permissions valid in that scope OR the <code>global</code> scope.</p>
            <pre><code class="language-python">@router.patch("/project/{project_id}/settings")
async def update_project(
    project_id: str,
    # Checks for permission "project:write:settings" in scope "project:{project_id}"
    user = Depends(PermissionChecker("project:write:settings", scope_from_path="project_id"))
):
    return {"status": "Project update authorized"}
</code></pre>
        `;

        pages['rbac-management'] = `
            <h1>RBAC Management (Admin API)</h1>
            <p>The <code>auth_service</code> exposes powerful asynchronous methods in its <code>roles</code> and <code>permissions</code> managers for administrative control over the RBAC system.</p>
            <p class="p-3 bg-red-900/50 rounded-lg">
                <strong>NOTE:</strong> The built-in Admin routes are currently subject to change. For stable, custom administration and integration with your application logic, it is highly recommended to use the core <b>Service Manager methods</b> (<code>auth_service.roles</code> and <code>auth_service.permissions</code>) directly.
            </p>

            <h2>Authorization for Management</h2>
            <p>AuthTuna uses a hybrid model combining hierarchy and explicit grants for managing roles. Management operations (like role/permission creation and user assignment) are controlled by three authorization rules, checked in order:</p>
            <ol class="list-decimal pl-6 space-y-2">
                <li><strong>Specific Permission Override:</strong> Does the administrator have a permission like <code>roles:assign:SomeRole</code>?</li>
                <li><strong>Role Hierarchy:</strong> Does the administrator's <b>highest role level</b> exceed the target role's <b>level</b>? (e.g., Admin level 90 can assign Moderator level 50).</li>
                <li><strong>Explicit Role Grant:</strong> Is the administrator's role explicitly granted permission to assign the target role (managed via <code>/admin/roles/grants/assign-role</code>)?</li>
            </ol>
            <p class="mt-4 p-3 bg-indigo-900/50 rounded-lg">
                <strong>Role Level Configuration:</strong>
                <ul>
                    <li>Set a role's <code>level</code> to a positive integer to enable <b>Hierarchical</b> authorization (Rule 2).</li>
                    <li>Set a role's <code>level</code> to <b>0</b> if you want the "system" default user to be able to assign it without explicit grants, but restrict human admins to using <b>Explicit Grants</b> (Rule 3).</li>
                    <li>Set a role's <code>level</code> to <b>None</b> (the default) to use a pure <b>Explicit Grant-based system</b> (Rule 3) only, requiring explicit grants for *all* assigners.</li>
                </ul>
            </p>

            <h2>Role and Permission CRUD (Service Layer)</h2>
            <p>The recommended way to manage the RBAC structure is directly through the <code>auth_service</code> methods.</p>

            <h3>1. Permission Creation and Management</h3>
            <p>The <code>PermissionManager</code> handles the creation and management of permissions.</p>
            <pre><code class="language-python">from authtuna.integrations import auth_service
from authtuna.manager.asynchronous import PermissionManager

# Create a new permission (Perm Creation)
new_perm = await auth_service.permissions.create(
    name="dashboard:view:summary",
    description="Allows viewing the analytics dashboard."
)

# Use get_or_create to safely ensure a permission exists
perm, created = await auth_service.permissions.get_or_create("data:view:summary")

# Permission Update: Permissions are generally managed by linking/unlinking them from roles,
# or by directly updating the database object via the PermissionManager if needed.
</code></pre>

            <h3>2. Role Creation and Management</h3>
            <p>The <code>RoleManager</code> handles core role definition.</p>
            <pre><code class="language-python">from authtuna.manager.asynchronous import RoleManager

# Role Creation
new_role = await auth_service.roles.create(
    name="VIP",
    description="High-priority customer role",
    level=75
)

# Adding/Linking Permissions to a Role
await auth_service.roles.add_permission_to_role(
    role_name="VIP",
    permission_name="dashboard:view:summary",
    adder_id="system" # The entity performing the action
)
</code></pre>

            <h3>3. Managing Assignment Grants (The Core of Role Management)</h3>
            <p>The <code>grant_relationship</code> method is crucial for configuring explicit authorization rules (Rule 3).</p>
            <pre><code class="language-python">from authtuna.manager.asynchronous import RoleManager, PermissionManager

# Grant Role Assignment (AssignerRole -> AssignableRole)
# 'can_assign_roles' enables Rule #3 for role management checks.
await auth_service.roles.grant_relationship(
    granter_role_name="Admin",
    grantable_name="Moderator",
    grantable_manager=auth_service.roles, # Use RoleManager for assigning roles
    relationship_attr="can_assign_roles"
)

# Grant Permission Assignment (GranterRole -> GrantablePermission)
await auth_service.roles.grant_relationship(
    granter_role_name="SuperAdmin",
    grantable_name="admin:manage:roles",
    grantable_manager=auth_service.permissions, # Use PermissionManager for granting perms
    relationship_attr="can_grant_permissions"
)
</code></pre>

            <h3>4. Assigning Users to Roles</h3>
            <p>This central operation triggers the three-part authorization check to ensure the <code>assigner_id</code> is authorized.</p>
            <pre><code class="language-python"># Add/Assign Users to a Role
await auth_service.roles.assign_to_user(
    user_id="user-12345",
    role_name="VIP",
    assigner_id="default-admin", # Must be an authorized admin/user
    scope="global" # Scope can be 'global' or resource-specific (e.g., 'project:42')
)
</code></pre>

            <h2>Default Roles and Users</h2>
            <p>When <code>AUTO_CREATE_DATABASE</code> is enabled, AuthTuna provisions essential roles and users for immediate administration and system security (defined in <code>authtuna/core/defaults.py</code>).</p>

            <h3 class="mt-8">Important Default User Security Note</h3>
            <p class="p-3 bg-red-900/50 rounded-lg">
                The <code>superadmin</code> and <code>admin</code> users are created <b>without a usable password</b> by default, so they cannot be logged into unless <code>DEFAULT_SUPERADMIN_PASSWORD</code> or <code>DEFAULT_ADMIN_PASSWORD</code> were explicitly configured in the <code>.env</code> file <b>before the first database initialization</b>. If configuration is missed, you must set the password directly via the Admin UI or programmatically using <code>auth_service.users.set_password()</code>.
            </p>

            <div class="overflow-x-auto">
                <table class="w-full text-sm text-left text-gray-400 rounded-lg">
                    <thead class="text-xs uppercase bg-gray-800 text-gray-300">
                        <tr>
                            <th scope="col" class="py-3 px-6">Role Name</th>
                            <th scope="col" class="py-3 px-6">Level</th>
                            <th scope="col" class="py-3 px-6">Key Permissions</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr class="bg-gray-900 border-b border-gray-800"><td class="py-4 px-6 font-medium text-white">System</td><td class="py-4 px-6">999</td><td class="py-4 px-6">Internal processes. Highest level, can assign any role (via hierarchy).</td></tr>
                        <tr class="bg-gray-900 border-b border-gray-800"><td class="py-4 px-6 font-medium text-white">SuperAdmin</td><td class="py-4 px-6">100</td><td class="py-4 px-6"><code>admin:manage:permissions</code>, <code>admin:manage:roles</code>, full management access.</td></tr>
                        <tr class="bg-gray-900 border-b border-gray-800"><td class="py-4 px-6 font-medium text-white">Admin</td><td class="py-4 px-6">90</td><td class="py-4 px-6"><code>admin:manage:users</code>, <code>admin:manage:roles</code> (limited by level).</td></tr>
                        <tr class="bg-gray-900 border-b border-gray-800"><td class="py-4 px-6 font-medium text-white">Moderator</td><td class="py-4 px-6">50</td><td class="py-4 px-6"><code>admin:access:panel</code>, <code>admin:manage:users</code> (suspend/edit).</td></tr>
                        <tr class="bg-gray-900 border-b border-gray-800"><td class="py-4 px-6 font-medium text-white">User</td><td class="py-4 px-6">10</td><td class="py-4 px-6">Standard application access.</td></tr>
                    </tbody>
                </table>
            </div>

            <h3 class="mt-8">Default Users</h3>
            <p>Three default users are created. The <b>system</b> user is an internal utility account and cannot be logged into by humans.</p>
            <ul>
                <li><strong>system:</strong> Internal ID: <code>system</code>. Used for audit logging and initial role assignments. Due to its high level (999), it can be used for automated role assignments without requiring explicit grants (if the role being assigned has a level < 999).</li>
                <li><strong>superadmin:</strong> Default Email: <code>settings.DEFAULT_SUPERADMIN_EMAIL</code>. Assigned <code>SuperAdmin</code> role.</li>
                <li><strong>admin:</strong> Default Email: <code>settings.DEFAULT_ADMIN_EMAIL</code>. Assigned <code>Admin</code> role.</li>
            </ul>
        `;

        pages['auth-flows'] = `
            <h1>Authentication Flows & Endpoints</h1>
            <p>The <code>auth_router</code>, <code>mfa_router</code>, and <code>social_router</code> provide all necessary API endpoints and HTML pages (templates) for a complete security system.</p>

            <h2>Standard Authentication (\`/auth\`)</h2>
            <p>These endpoints handle credentials and password security.</p>
            <div class="overflow-x-auto">
                <table class="w-full text-sm text-left text-gray-400 rounded-lg">
                    <thead class="text-xs uppercase bg-gray-800 text-gray-300">
                        <tr>
                            <th scope="col" class="py-3 px-6">Endpoint</th>
                            <th scope="col" class="py-3 px-6">Method</th>
                            <th scope="col" class="py-3 px-6">Function</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr class="bg-gray-900 border-b border-gray-800"><td class="py-4 px-6">/auth/signup</td><td>GET/POST</td><td>User registration and template rendering.</td></tr>
                        <tr class="bg-gray-900 border-b border-gray-800"><td class="py-4 px-6">/auth/login</td><td>GET/POST</td><td>User login (returns session or MFA token) and template rendering.</td></tr>
                        <tr class="bg-gray-900 border-b border-gray-800"><td class="py-4 px-6">/auth/logout</td><td>GET/POST</td><td>Terminates current session and clears cookie.</td></tr>
                        <tr class="bg-gray-900 border-b border-gray-800"><td class="py-4 px-6">/auth/verify</td><td>GET</td><td>Validates email verification token.</td></tr>
                        <tr class="bg-gray-900 border-b border-gray-800"><td class="py-4 px-6">/auth/change-password</td><td>POST</td><td>Allows authenticated users to update their password.</td></tr>
                    </tbody>
                </table>
            </div>
        `;

        pages['mfa'] = `
            <h1>MFA & Social Login (SSO)</h1>

            <h2>Multi-Factor Authentication (\`/mfa\`)</h2>
            <p>AuthTuna implements the TOTP standard (compatible with Google Authenticator, Authy, etc.) along with recovery codes.</p>
            <div class="overflow-x-auto">
                <table class="w-full text-sm text-left text-gray-400 rounded-lg">
                    <thead class="text-xs uppercase bg-gray-800 text-gray-300">
                        <tr>
                            <th scope="col" class="py-3 px-6">Endpoint</th>
                            <th scope="col" class="py-3 px-6">Method</th>
                            <th scope="col" class="py-3 px-6">Purpose</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr class="bg-gray-900 border-b border-gray-800"><td class="py-4 px-6">/mfa/setup</td><td>GET/POST</td><td>Generates TOTP secret/QR code URI and template.</td></tr>
                        <tr class="bg-gray-900 border-b border-gray-800"><td class="py-4 px-6">/mfa/verify</td><td>POST</td><td>Verifies code to enable MFA and returns backup codes.</td></tr>
                        <tr class="bg-gray-900 border-b border-gray-800"><td class="py-4 px-6">/mfa/validate-login</td><td>POST</td><td>Completes login using MFA code or recovery code.</td></tr>
                        <tr class="bg-gray-900 border-b border-gray-800"><td class="py-4 px-6">/mfa/disable</td><td>POST</td><td>Disables MFA for the current user.</td></tr>
                    </tbody>
                </table>
            </div>

            <h2>Social Login (\`/auth/{provider}\`)</h2>
            <p>If configured, the <code>social_router</code> handles OAuth2/OIDC flows for providers like Google and GitHub, automatically linking or creating user accounts.</p>
            <pre><code class="language-python"># Example: Google Login
/auth/google/login
/auth/google/callback
</code></pre>
        `;

        pages['middleware-session'] = `
            <h1>Middleware & Session Management</h1>
            <p>The <code>DatabaseSessionMiddleware</code> is the core security component that executes on every request.</p>

            <h2>Middleware Logic</h2>
            <p>The middleware performs the following steps:</p>
            <ol class="list-decimal pl-6 space-y-2">
                <li>Extracts the encrypted JWT session token from the cookie (or Bearer header).</li>
                <li>Decodes the token to get the <code>session_id</code>, <code>user_id</code>, and <code>random_string</code>.</li>
                <li>If a database check is needed (controlled by <code>SESSION_DB_VERIFICATION_INTERVAL</code>):
                    <ul>
                        <li>Fetches the full session record from the database.</li>
                        <li>Verifies the session is active and not expired.</li>
                        <li>Checks for <b>Session Hijack</b> (mismatch in Region, Device, or Random String). If detected, session is <b>invalidated</b>.</li>
                        <li>Updates the session's <code>last_ip</code> and <code>mtime</code>.</li>
                        <li><b>Rotates</b> the <code>random_string</code> in the DB for the next request.</li>
                    </ul>
                </li>
                <li>Sets <code>request.state.user_id</code>, <code>request.state.session_id</code>, and <code>request.state.user_ip_address</code> for use by dependencies.</li>
                <li>Updates the response cookie with the new token (containing the rotated random string).</li>
            </ol>

            <h2>Session Hijack Protection</h2>
            <p>AuthTuna actively validates session integrity using device fingerprints collected by the middleware. If a request claims to be an active session but originates from a different device, the session is terminated immediately.</p>
        `;


        // --- Navigation Logic ---
        function navigate(pageId) {
            // 1. Update Content
            contentDiv.innerHTML = pages[pageId] || `<h1>404</h1><p>Documentation page not found for "\${pageId}".</p>`;

            // 2. Run Syntax Highlighting
            hljs.highlightAll();

            // 3. Update Active Class
            navLinks.forEach(link => {
                link.classList.remove('bg-indigo-600', 'text-white', 'font-semibold');
                link.classList.add('text-gray-300');
                if (link.getAttribute('data-page') === pageId) {
                    link.classList.add('bg-indigo-600', 'text-white', 'font-semibold');
                    link.classList.remove('text-gray-300');
                }
            });

            // 4. Update URL Hash
            history.pushState(null, null, '#' + pageId);

            // 5. Scroll to top on new page load
            document.querySelector('.doc-content-area').scrollTop = 0;
        }

        // Initialize on load
        document.addEventListener('DOMContentLoaded', () => {
            const initialPage = window.location.hash.substring(1) || 'introduction';
            navigate(initialPage);
        });

        // Handle browser back/forward buttons
        window.onpopstate = () => {
             const pageId = window.location.hash.substring(1) || 'introduction';
             navigate(pageId);
        };
    </script>
</body>
</html>
